/*
 * Description: office addins handler
 */
#include "office_addins_accelerator.h"
#include <unordered_map>
#include "Windows.h"
#include "performance/utils/perf_utils.h"
#include "performance/perf_constants.h"
#include "performance/preload/preload_app_path_manager.h"
#include "log.h"

namespace PERF {

#ifdef UNICODE
const TString ADDIN_SUB_KEY_BASE = L"Software\\Microsoft\\Office\\";
const TString ADDIN_SUB_KEY_WORD = L"Word\\AddIns\\MSOfficePLUS";
const TString ADDIN_SUB_KEY_EXCEL = L"Excel\\AddIns\\MSOfficePLUS";
const TString ADDIN_SUB_KEY_POWERPOINT = L"PowerPoint\\AddIns\\MSOfficePLUS";
const TString FIELD_LOAD_BEHAVIOR = L"LoadBehavior";
const TString SEP_BACKSLASH = L"\\";
const TString STR_EMPTY = L"";

#else
const TString ADDIN_SUB_KEY_BASE = "Software\\Microsoft\\Office\\";
const TString ADDIN_SUB_KEY_WORD = "Word\\AddIns\\MSOfficePLUS";
const TString ADDIN_SUB_KEY_EXCEL = "Excel\\AddIns\\MSOfficePLUS";
const TString ADDIN_SUB_KEY_POWERPOINT = "PowerPoint\\AddIns\\MSOfficePLUS";
const TString FIELD_LOAD_BEHAVIOR = "LoadBehavior";
const TString SEP_BACKSLASH = "\\";
const TString STR_EMPTY = "";
const TString REG_KEY_VMAGENT_OFFICE = "Software\\vmagent\\office";
const TString REG_ITEM_PREFIX_VMAGENT_CLOSE_OFFICE_PLUS_ADDIN = "CloseOfficePlusAddinOperated_";
#endif

const std::unordered_map<TString, TString> appNameToSubKey = { { PNAME_WORD, ADDIN_SUB_KEY_WORD },
                                                               { PNAME_EXCEL, ADDIN_SUB_KEY_EXCEL },
                                                               { PNAME_POWERPOINT, ADDIN_SUB_KEY_POWERPOINT } };
const DWORD LOAD_BEHAVIOR_VALUE_ON_DEMAND = 16;
const DWORD LOAD_BEHAVIOR_VALUE_AT_STARTUP = 3;
const DWORD LOAD_BEHAVIOR_VALUE_DO_NOT_LOAD = 2;
const DWORD REG_DWORD_VMAGENT_OFFICE_CLOSED = 1;

bool OfficeAddinsAccelerator::OnBegin(std::shared_ptr<PerfInfo> perfInfo)
{
    if (perfInfo == nullptr) {
        LOG_ERR("perfinfo is nulptr");
        return false;
    }
    if (perfInfo->scene == PERF::PERF_SCENE::APP_INSTALL) {
        LOG_INFO("[PERF - OnBegin] - meet install scene");
        return false;
    }
    LOG_INFO("OfficeAddinsAccelerator OnBegin. {}", perfInfo->appName);
    auto iterAppNameToHKey = appNameToSubKey.find(perfInfo->appName);
    if (iterAppNameToHKey == appNameToSubKey.end()) {
        perfInfo->skipSign |= SKIP_SIGN_OFFICE_ADDINS;
        return true;
    }
    HKEY hkcu = nullptr;
    REGISTRY_UTILS.GetHKCU(hkcu);
    if (!hkcu) {
        LOG_ERR("[PERF - OnBegin] - hkcu is nullptr");
        return false;
    }
    RegistryUtilsEx agentReg(hkcu, REG_KEY_VMAGENT_OFFICE);
    DWORD value = 0;
    LSTATUS status = agentReg.RegGetDword(REG_ITEM_PREFIX_VMAGENT_CLOSE_OFFICE_PLUS_ADDIN + perfInfo->appName, value);
    if (status == ERROR_SUCCESS) {
        return true;
    }
    if (status == ERROR_FILE_NOT_FOUND) {
        RegistryUtilsEx officeReg(hkcu, ADDIN_SUB_KEY_BASE + iterAppNameToHKey->second);
        officeReg.RegSetDword(FIELD_LOAD_BEHAVIOR, LOAD_BEHAVIOR_VALUE_DO_NOT_LOAD);
        agentReg.RegSetDword(REG_ITEM_PREFIX_VMAGENT_CLOSE_OFFICE_PLUS_ADDIN + perfInfo->appName,
                             REG_DWORD_VMAGENT_OFFICE_CLOSED);
        return true;
    } else {
        LOG_ERR("[PERF - OnBegin] - get reg failed");
        return false;
    }
}

bool OfficeAddinsAccelerator::OnEnd(std::shared_ptr<PerfInfo> perfInfo)
{
    if (perfInfo->scene == PERF::PERF_SCENE::APP_INSTALL) {
        LOG_INFO("[PERF - OnEnd] - meet install scene");
        return false;
    }
    return true;
}

}  // namespace PERF